
#pragma once

#include <ttg/all.h>
#include "Sphere.h"
#include "cudaBindings.h"
#include "PipelineTests.h"

using namespace ttg::math;
using namespace ttg::pipeline;

//Calculates sum of intersection depth for each incoming sphere.
//Results will be sent as a vector of sums with the same dimensions.
class IntersectionFinder :public Node<std::vector<Sphere> *,
									  std::vector<float>>
{
	public:
		//Calculating sums of intersection depths.
		virtual void process(std::vector<Sphere> *data)
		{
			std::vector<Sphere> &spheres = *data;
			std::vector<float> res(spheres.size(), 0.0f);
			for (size_t i = 0; i < spheres.size(); i++)
				for (size_t j = i + 1; j < spheres.size(); j++)
					res[i] += Sphere::findIntersectionDepth(spheres[i], spheres[j]);
			sendNext(res);
		}
		//Adds bindings for CUDA technology.
		inline IntersectionFinder()
		{ addBinding(new cudaIntersectionFinder()); }
};

//Sums all intersection depths together.
class IntersectionSummator :public Node<std::vector<float>, float>
{
	public:
		virtual void process(std::vector<float> data)
		{
			float res = 0.0f;
			for (size_t i = 0; i < data.size(); i++)
				res += data[i];
			sendNext(res);
		}
};

int main()
{
	//Initing services and creating pipeline.
	ttg::services::Services s(true);
	Pipeline<std::vector<Sphere> *, float> pl(wrap(new IntersectionFinder()) +
											  wrap(new IntersectionSummator()));
	//Testing.
	double t_elapsed;
	//Test #1.
	printf("Test #1 ... ");
	if (pipelineTest1(pl, t_elapsed))
		printf("passed, elapsed time: %lf ms\n", t_elapsed);
	else
		printf("failed\n");
	//Test #2.
	printf("Test #2 ... ");
	if (pipelineTest2(pl, t_elapsed))
		printf("passed, elapsed time: %lf ms\n", t_elapsed);
	else
		printf("failed\n");
	//Test #3.
	printf("Test #3 ... ");
	if (pipelineTest3(pl, t_elapsed))
		printf("passed, elapsed time: %lf ms\n", t_elapsed);
	else
		printf("failed\n");
	exit(0);
}
